package net.kunyv.base.shiro;

import net.kunyv.base.entity.SysUser;
import net.kunyv.base.service.SysRoleResourceService;
import net.kunyv.base.service.SysUserRoleService;
import net.kunyv.base.service.SysUserService;
import net.kunyv.util.HdUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
@DependsOn({"SystemUserService"})
public class ShiroRealm extends AuthorizingRealm {
    public Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleResourceService sysRoleResourceService;

    /**
     * 权限认证（为当前登录的Subject授予角色和权限）
     * <p>
     * 该方法的调用时机为需授权资源被访问时，并且每次访问需授权资源都会执行该方法中的逻辑，这表明本例中并未启用AuthorizationCache，
     * 如果连续访问同一个URL（比如刷新），该方法不会被重复调用，Shiro有一个时间间隔（也就是cache时间，在ehcache-shiro.xml中配置），
     * 超过这个时间间隔再刷新页面，该方法会被执行
     * <p>
     * doGetAuthorizationInfo()是权限控制，
     * 当访问到页面的时候，使用了相应的注解或者shiro标签才会执行此方法否则不会执行，
     * 所以如果只是简单的身份认证没有权限的控制的话，那么这个方法可以不进行实现，直接返回null即可
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 从session中拿出用户对象
        SysUser user = HdUtil.getLoginUser();
        //获取用户角色
        List<String> permissionList = sysRoleResourceService.getUserPermissionByUserId(user.getUserId());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionList);
        return info;
    }

    /**
     * 登录认证
     *
     * @param
     * @return
     * @author sunyb
     * @date 2016-12-29
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        SysUser sysUser = sysUserService.getUserByUserName(username.trim().toLowerCase());
        if (null != sysUser) {
            return new SimpleAuthenticationInfo(username, sysUser.getPassword(), this.getName());
        } else {
            // 认证没有通过
            throw new UnknownAccountException();// 没帐号
        }
    }

}
